home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / HippoDraw / hippo / hippoplotNeXT.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-28  |  20.2 KB  |  794 lines

  1. /*
  2.  * hippoplotps.c - Postscript routines for displaying hippo ntuples.
  3.  *
  4.  * Copyright (C)  1991  The Board of Trustees of The Leland Stanford
  5.  * Junior University.  All Rights Reserved.
  6.  *
  7.  * $Header: /nfs/ebnextk/LocalSources/hippo/RCS/hippoplotNeXT.c,v 3.4 1992/03/12 02:07:32 rensing Rel $
  8.  *
  9.  * by jonas karlsson, at SLAC, August 1990
  10.  *  split up by Paul Rensing, Feb 28,1991
  11.  *  modified by M. Gravina, March 28, 1991
  12.  */
  13.  
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <math.h>
  17. #include  <appkit/graphics.h>
  18. #include  <appkit/color.h>
  19. #include  <dpsclient/psops.h>
  20. #include  <dpsclient/wraps.h>
  21. #include  <dpsclient/dpsclient.h>
  22. #include "hippo.h"
  23. #include "hippoplotNeXT.h"
  24. #include "hippoutil.h"
  25.  
  26. /* find offset to matrix element */
  27. #define INDEX(row, column, totcols) ((row) * (totcols) + (column))
  28.  
  29. #define MIN(x, y)  (((x) > (y)) ? (y) : (x))
  30.  
  31. /* following copied from <appkit/View.h> */
  32. /* look out of changes in future releases */
  33. extern short NXDrawingStatus;
  34.  
  35. /* NXDrawingStatus values */
  36.  
  37. #define NX_DRAWING    1    /* we're drawing */
  38. #define NX_PRINTING    2    /* we're printing */
  39. #define NX_COPYING    3    /* we're copying to the scrap */
  40.  
  41. /*
  42.  * maximum number of point to use in userpaths
  43.  */
  44. #define MAXNPTS_SCREEN 1000
  45. #define MAXNPTS_PRINT 500
  46.  
  47. /* various globals */
  48.  
  49. rectangle outerRect;    /* Outer rectangle in device units */
  50. rectangle innerRect;    /* inner (ie plotting area) rectangle in device units */
  51. rectangle userRect;    /* ditto in user units */ 
  52. float bbox[4];            /* bounding box required by DPSDoUserPath */
  53. float xScale, yScale;    /* used for getting into user coords from device coords */
  54.  
  55. int initPlot_NeXT(rectangle *rect1, rectangle *rect2, rectangle *rect3)
  56. {
  57.     /* Save rectangle pointers for global use */
  58.     memcpy((char *) &outerRect, (const char *)rect1, sizeof(rectangle) );
  59.     memcpy((char *) &innerRect, (const char *)rect2, sizeof(rectangle) );
  60.     memcpy((char *) &userRect, (const char *)rect3, sizeof(rectangle) );
  61.     
  62.     xScale = innerRect.size.width / userRect.size.width;
  63.     yScale = innerRect.size.height / userRect.size.height;
  64.  
  65.     /* specify bounding box  (add a small margin for safety) */    
  66.     bbox[0] = userRect.origin.x -
  67.          (innerRect.origin.x - outerRect.origin.x)/xScale;
  68.     bbox[1] = userRect.origin.y - 
  69.          (innerRect.origin.y - outerRect.origin.y)/yScale;
  70.     bbox[2] = userRect.origin.x + userRect.size.width +
  71.          (outerRect.size.width+outerRect.origin.x - 
  72.           (innerRect.origin.x+innerRect.size.width))/xScale;
  73.     bbox[3] = userRect.origin.y + userRect.size.height +
  74.          (outerRect.size.height+outerRect.origin.y - 
  75.           (innerRect.origin.y+innerRect.size.height))/yScale;
  76.  
  77.     return 0;
  78. }
  79.  
  80. int drawLine_NeXT(float *coords, int nCoords, linestyle_t ls)
  81. {
  82.      char ops[3] = { dps_moveto, 0, dps_lineto };
  83.      int repeatCount;        /* this number + 32 must be < 255 */
  84.                      /* to display and < 127 for printing */
  85.                 /* to fit in 1 char */
  86.      float *co;
  87.      int count;
  88.      float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
  89.  
  90.      if ( NXDrawingStatus == NX_DRAWING )
  91.         repeatCount = 220;
  92.      else
  93.         repeatCount = 92;    /* work around apparent bug */
  94.      PSgsave();
  95. /*         PSsetlinewidth(0.15);   NeXT's magic number for fast drawing */
  96.                  /* in case going to Linotronic (R) */
  97.      
  98.      /* get into user coords */
  99.      PStranslate (innerRect.origin.x, innerRect.origin.y);
  100.      PSscale (xScale, yScale);
  101.      PStranslate (-userRect.origin.x, -userRect.origin.y);
  102.      
  103.      /* 
  104.       * the following rather messy code is needed because PostScript
  105.       * uses just 1 character for a repeat counter (specified as
  106.       * 'excess 32').  Using the repeat method means we don't have to
  107.       * malloc some variable length array for the ops, and then free
  108.       * it after use.
  109.       */
  110.      co = coords;
  111.      do
  112.      {
  113.       if (nCoords > repeatCount) count = repeatCount;
  114.       else count = nCoords;
  115.       /*
  116.        * use DPSDoUserPathWithMatrix to take care of funny effect when
  117.        * you have unequal scaling.
  118.        */
  119.       ops[1] = 32 + count - 1;
  120.       DPSDoUserPathWithMatrix(co, 2*count, dps_float, ops, 3, 
  121.                   bbox, dps_ustroke, ctm_matrix);
  122.       co += 2*(count - 1);
  123.       nCoords -= (count - 1);
  124.      }
  125.      while (nCoords > 1);    /* 1 because we always back up 1 point */
  126.                 /*  to connect the segments */
  127.  
  128.      PSgrestore();
  129.      return 0;
  130. }
  131.  
  132.  
  133.  
  134. int drawPoints_NeXT(float *coords, int nCoords, plotsymbol_t symbol,
  135.             float symbolSize)
  136. {
  137.  
  138.      int ci, oi, i;
  139.      int filled=0;
  140.      int count;
  141.      int maxnpts;
  142.      float *cArray;
  143.      char *oArray;
  144.      float xPointSide, yPointSide;
  145.      float xHalfPointSide, yHalfPointSide;
  146.      float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
  147.  
  148.      if ( NXDrawingStatus == NX_DRAWING )
  149.       maxnpts = MAXNPTS_SCREEN;
  150.      else
  151.       maxnpts = MAXNPTS_PRINT;
  152.      
  153.      if (symbol == SOLIDSQUARE)
  154.       filled = 1;
  155.      
  156.      if (filled) maxnpts /= 5;
  157.  
  158.      xPointSide = symbolSize / xScale;
  159.      yPointSide = symbolSize / yScale;
  160.      xHalfPointSide = xPointSide / 2.0;
  161.      yHalfPointSide = yPointSide / 2.0;
  162.      
  163.      PSgsave();
  164. /*     PSsetlinewidth(0.15);     NeXT's magic number for fast drawing */
  165.      
  166.      /* get into user coords */
  167.      PStranslate (innerRect.origin.x, innerRect.origin.y);
  168.      PSscale (xScale, yScale);
  169.      PStranslate (-userRect.origin.x, -userRect.origin.y);
  170.  
  171.      if (nCoords > maxnpts) i = maxnpts;
  172.      else i = nCoords;
  173.      if ((cArray = (float *) malloc( 8*i * sizeof(float) )) == NULL)
  174.      {
  175.       h_error("drawPoints_NeXT - memory exceeded ");
  176.       return -1;
  177.      }
  178.      
  179.      if ((oArray = (char *) malloc( 5*i * sizeof(char) )) == NULL)
  180.      {
  181.       h_error("drawPoints_NeXT - memory exceeded ");
  182.       return -1;
  183.      }
  184.      
  185.      do
  186.      {
  187.       if (nCoords > maxnpts) count = maxnpts;
  188.       else count = nCoords;
  189.       
  190.       ci = oi = 0;
  191.       
  192.       switch (symbol)
  193.       {
  194.       case SQUARE:
  195.       case SOLIDSQUARE:
  196.            for (i = 0; i < count; i++)
  197.            {
  198.             cArray[ci++] = *coords++ - xHalfPointSide;     
  199.             cArray[ci++] = *coords++ - yHalfPointSide;
  200.             oArray[oi++] = dps_moveto;
  201.             
  202.             cArray[ci++] = +xPointSide;
  203.             cArray[ci++] = +0.0;
  204.             oArray[oi++] = dps_rlineto;
  205.             
  206.             cArray[ci++] = +0.0;
  207.             cArray[ci++] = +yPointSide;
  208.             oArray[oi++] = dps_rlineto;
  209.             
  210.             cArray[ci++] = -xPointSide;
  211.             cArray[ci++] = +0.0;
  212.             oArray[oi++] = dps_rlineto;
  213.             oArray[oi++] = dps_closepath;
  214.            }
  215.            break;
  216.            
  217.       case PLUS:
  218.            for (i = 0; i < count; i++)
  219.            {
  220.             cArray[ci++] = *coords++ - xHalfPointSide;     
  221.             cArray[ci++] = *coords++;
  222.             oArray[oi++] = dps_moveto;
  223.             
  224.             cArray[ci++] = +xPointSide;
  225.             cArray[ci++] = +0.0;
  226.             oArray[oi++] = dps_rlineto;
  227.             
  228.             cArray[ci++] = -xHalfPointSide;
  229.             cArray[ci++] = +yHalfPointSide;
  230.             oArray[oi++] = dps_moveto;
  231.             
  232.             cArray[ci++] = 0.0;
  233.             cArray[ci++] = -yPointSide;
  234.             oArray[oi++] = dps_rlineto;
  235.            }
  236.            break;
  237.            
  238.       case TIMES:
  239.            for (i = 0; i < count; i++)
  240.            {
  241.             cArray[ci++] = *coords++ - xHalfPointSide;     
  242.             cArray[ci++] = *coords++ - yHalfPointSide;
  243.             oArray[oi++] = dps_moveto;
  244.             
  245.             cArray[ci++] = +xPointSide;
  246.             cArray[ci++] = +yPointSide;
  247.             oArray[oi++] = dps_rlineto;
  248.             
  249.             cArray[ci++] = 0.0;
  250.             cArray[ci++] = +yPointSide;
  251.             oArray[oi++] = dps_moveto;
  252.             
  253.             cArray[ci++] = -xPointSide;
  254.             cArray[ci++] = -yPointSide;
  255.             oArray[oi++] = dps_rlineto;
  256.            }
  257.            break;
  258.            
  259.       default:
  260.            break;
  261.       }
  262.       
  263.       /*
  264.        * use DPSDoUserPathWithMatrix to take care of funny effect when
  265.        * you have unequal scaling. Applies to line widths and patterns,
  266.        * so not useful for filled symbols.
  267.        */
  268.       if (filled)
  269.            DPSDoUserPath(cArray, ci, dps_float, oArray, oi, bbox, 
  270.                  dps_ufill);
  271.       else
  272.            DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox,
  273.                        dps_ustroke,ctm_matrix);
  274.  
  275.       nCoords -= count;
  276.      }
  277.      while (nCoords > 0);
  278.      
  279.      free (cArray);
  280.      free (oArray);
  281.      PSgrestore();
  282.  
  283.      return 0;
  284. }
  285.  
  286.  
  287. int drawYError_NeXT(float *coords, float *errorYs, int nCoords)
  288. {
  289. #define ERRORCAPSIZE 2.0
  290.  
  291.      int ci, oi, i;
  292.      int count;
  293.      int maxnpts;
  294.      float *cArray;
  295.      char *oArray;
  296.      float halfErrorCap = ERRORCAPSIZE/xScale * 0.5;
  297.      float x, ylo, yhi; 
  298.      float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
  299.  
  300.      if ( NXDrawingStatus == NX_DRAWING )
  301.       maxnpts = MAXNPTS_SCREEN;
  302.      else
  303.       maxnpts = MAXNPTS_PRINT;
  304.  
  305.      if (nCoords > maxnpts) i = maxnpts;
  306.      else i = nCoords;
  307.      if ((cArray = (float *) malloc (12 * i * sizeof(float))) == NULL)
  308.      {
  309.       h_error("drawYError_NeXT - memory exceeded ");
  310.       return -1;
  311.      }
  312.      
  313.      if ((oArray = (char *) malloc (6 * i * sizeof(char))) == NULL)
  314.      {
  315.       h_error("drawYError_NeXT - memory exceeded ");
  316.       return -1;
  317.      }
  318.      
  319.      PSgsave();
  320. /*     PSsetlinewidth(0.15);     NeXT's magic number for fast drawing */
  321.      
  322.      /* get into user coords */
  323.      PStranslate (innerRect.origin.x, innerRect.origin.y);
  324.      PSscale (xScale, yScale);
  325.      PStranslate (-userRect.origin.x, -userRect.origin.y);
  326.      
  327.      do 
  328.      {
  329.       if (nCoords > maxnpts) count = maxnpts;
  330.       else count = nCoords;
  331.       
  332.       ci = oi = 0;
  333.       
  334.       for (i = 0; i < count; i++)
  335.       {
  336.            x = *coords++;    /* x coord */
  337.            coords++;    /* skip over this y coord - not needed */
  338.            yhi = *errorYs++; /* y of high end of error bar */
  339.            ylo = *errorYs++; /* y of low end of error bar */
  340.            
  341.            cArray[ci++] = x;     
  342.            cArray[ci++] = ylo;
  343.            oArray[oi++] = dps_moveto; /* move to mid bottom */
  344.       
  345.            cArray[ci++] = x;
  346.            cArray[ci++] = yhi;
  347.            oArray[oi++] = dps_lineto;        /* line to mid top */
  348.            
  349.            cArray[ci++] = x - halfErrorCap;
  350.            cArray[ci++] = yhi;
  351.            oArray[oi++] = dps_moveto; /* move to top left */
  352.            
  353.            cArray[ci++] = x + halfErrorCap;
  354.            cArray[ci++] = yhi;
  355.            oArray[oi++] = dps_lineto; /* line to top right */
  356.            
  357.            cArray[ci++] = x - halfErrorCap;
  358.            cArray[ci++] = ylo;
  359.            oArray[oi++] = dps_moveto; /* move to bottom left */
  360.            
  361.            cArray[ci++] = x + halfErrorCap;
  362.            cArray[ci++] = ylo;
  363.            oArray[oi++] = dps_lineto; /* line to bottom right */
  364.       }
  365.       
  366.       DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox, 
  367.                   dps_ustroke, ctm_matrix);
  368.       nCoords -= count;
  369.      }
  370.      while (nCoords > 0);
  371.  
  372.      PSgrestore();
  373.      
  374.      free (cArray);
  375.      free (oArray);
  376.      return 0;
  377. }
  378.  
  379.  
  380. int drawXError_NeXT(float *coords, float *errorXs, int nCoords)
  381. {
  382.      int ci, oi, i;
  383.      int count;
  384.      int maxnpts;
  385.      float *cArray;
  386.      char *oArray;
  387.      float halfErrorCap = ERRORCAPSIZE/yScale * 0.5;
  388.      float y, xlo, xhi; 
  389.      float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
  390.  
  391.      if ( NXDrawingStatus == NX_DRAWING )
  392.       maxnpts = MAXNPTS_SCREEN;
  393.      else
  394.       maxnpts = MAXNPTS_PRINT;
  395.  
  396.      if (nCoords > maxnpts) i = maxnpts;
  397.      else i = nCoords;
  398.      if ((cArray = (float *) malloc (12 * i * sizeof(float))) == NULL)
  399.      {
  400.       h_error("drawXError_NeXT - memory exceeded ");
  401.       return -1;
  402.      }
  403.      
  404.      if ((oArray = (char *) malloc (6 * i * sizeof(char))) == NULL)
  405.      {
  406.       h_error("drawXError_NeXT - memory exceeded ");
  407.       return -1;
  408.      }
  409.      
  410.      PSgsave();
  411. /*     PSsetlinewidth(0.15);     NeXT's magic number for fast drawing */
  412.      
  413.      /* get into user coords */
  414.      PStranslate (innerRect.origin.x, innerRect.origin.y);
  415.      PSscale (xScale, yScale);
  416.      PStranslate (-userRect.origin.x, -userRect.origin.y);
  417.      
  418.      do 
  419.      {
  420.       if (nCoords > maxnpts) count = maxnpts;
  421.       else count = nCoords;
  422.       
  423.       ci = oi = 0;
  424.       
  425.       for (i = 0; i < count; i++)
  426.       {
  427.            coords++;    /* skip over this x coord - not needed */
  428.            y = *coords++;    /* y coord */
  429.            xhi = *errorXs++; /* x of high end of error bar */
  430.            xlo = *errorXs++; /* x of low end of error bar */
  431.            
  432.            cArray[ci++] = xlo;     
  433.            cArray[ci++] = y;
  434.            oArray[oi++] = dps_moveto; /* move to mid bottom */
  435.       
  436.            cArray[ci++] = xhi;
  437.            cArray[ci++] = y;
  438.            oArray[oi++] = dps_lineto;        /* line to mid top */
  439.            
  440.            cArray[ci++] = xlo;
  441.            cArray[ci++] = y - halfErrorCap;
  442.            oArray[oi++] = dps_moveto; /* move to top left */
  443.            
  444.            cArray[ci++] = xlo;
  445.            cArray[ci++] = y + halfErrorCap;
  446.            oArray[oi++] = dps_lineto; /* line to top right */
  447.            
  448.            cArray[ci++] = xhi;
  449.            cArray[ci++] = y - halfErrorCap;
  450.            oArray[oi++] = dps_moveto; /* move to bottom left */
  451.            
  452.            cArray[ci++] = xhi;
  453.            cArray[ci++] = y + halfErrorCap;
  454.            oArray[oi++] = dps_lineto; /* line to bottom right */
  455.       }
  456.       
  457.       DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox, 
  458.                   dps_ustroke, ctm_matrix);
  459.       nCoords -= count;
  460.      }
  461.      while (nCoords > 0);
  462.  
  463.      PSgrestore();
  464.      
  465.      free (cArray);
  466.      free (oArray);
  467.      return 0;
  468. }
  469.  
  470. int drawYTicks_NeXT( float *y, int nt, float tickwidth, int side )
  471. {
  472.      int ci, oi, i;
  473.      float *cArray;
  474.      char *oArray;
  475.      float start;
  476.      float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
  477.      
  478.      tickwidth /= xScale;
  479.      
  480.      if (side == 0) 
  481.       start = userRect.origin.x;
  482.      else
  483.       start = userRect.origin.x + userRect.size.width - tickwidth;
  484.  
  485.      if ((cArray = (float *) malloc (4 * nt * sizeof(float))) == NULL)
  486.      {
  487.       h_error("drawYTicks_NeXT - memory exceeded ");
  488.       return -1;
  489.      }
  490.      
  491.      if ((oArray = (char *) malloc (2 * nt * sizeof(char))) == NULL)
  492.      {
  493.       h_error("drawYTicks_NeXT - memory exceeded ");
  494.       return -1;
  495.      }
  496.      
  497.      PSgsave();
  498.      
  499.      /* get into user coords */
  500.      PStranslate (innerRect.origin.x, innerRect.origin.y);
  501.      PSscale (xScale, yScale);
  502.      PStranslate (-userRect.origin.x, -userRect.origin.y);
  503.      
  504.      ci = oi = 0;
  505.      
  506.      for (i = 0; i < nt; i++)
  507.      {
  508.       cArray[ci++] = start;
  509.       cArray[ci++] = y[i];
  510.       oArray[oi++] = dps_moveto;
  511.       
  512.       cArray[ci++] = tickwidth;
  513.       cArray[ci++] = 0.0;
  514.       oArray[oi++] = dps_rlineto;
  515.      }
  516.      DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox, 
  517.                  dps_ustroke, ctm_matrix);
  518.      PSgrestore();
  519.  
  520.      free(cArray);
  521.      free(oArray);
  522.      
  523.      return 0;
  524. }
  525.  
  526. int drawXTicks_NeXT( float *y, int nt, float tickwidth, int side )
  527. {
  528.      int ci, oi, i;
  529.      float *cArray;
  530.      float start;
  531.      char *oArray;
  532.      float ctm_matrix[6] = {1.0/xScale, 0.0, 0.0, 1.0/yScale, 0.0, 0.0 };
  533.      
  534.      tickwidth /= yScale;
  535.  
  536.      if (side == 0) 
  537.       start = userRect.origin.y;
  538.      else
  539.       start = userRect.origin.y + userRect.size.height - tickwidth;
  540.      
  541.      if ((cArray = (float *) malloc (4 * nt * sizeof(float))) == NULL)
  542.      {
  543.       h_error("drawYTicks_NeXT - memory exceeded ");
  544.       return -1;
  545.      }
  546.      
  547.      if ((oArray = (char *) malloc (2 * nt * sizeof(char))) == NULL)
  548.      {
  549.       h_error("drawYTicks_NeXT - memory exceeded ");
  550.       return -1;
  551.      }
  552.      
  553.      PSgsave();
  554.      
  555.      /* get into user coords */
  556.      PStranslate (innerRect.origin.x, innerRect.origin.y);
  557.      PSscale (xScale, yScale);
  558.      PStranslate (-userRect.origin.x, -userRect.origin.y);
  559.      
  560.      ci = oi = 0;
  561.      
  562.      for (i = 0; i < nt; i++)
  563.      {
  564.       cArray[ci++] = y[i];
  565.       cArray[ci++] = start; 
  566.       oArray[oi++] = dps_moveto;
  567.       
  568.       cArray[ci++] = 0.0;
  569.       cArray[ci++] = tickwidth;
  570.       oArray[oi++] = dps_rlineto;
  571.      }
  572.      DPSDoUserPathWithMatrix(cArray, ci, dps_float, oArray, oi, bbox, 
  573.                  dps_ustroke, ctm_matrix);
  574.      PSgrestore();
  575.  
  576.      free(cArray);
  577.      free(oArray);
  578.      
  579.      return 0;
  580. }
  581.  
  582. int drawMag_NeXT(float x, float y, int mag, float fontSize)
  583. {
  584.      char str[10];
  585.      
  586.      PSselectfont("Helvetica",fontSize);
  587.      PSmoveto( x, y );
  588.      PSshow("x10");
  589.      PSrmoveto( 0.0, 0.5*fontSize );
  590.      sprintf(str,"%d",mag);
  591.      PSshow(str);
  592.      
  593.      return 0;
  594. }
  595.  
  596.  
  597. int drawText_NeXT(char *string, float x, float y, float fontSize, 
  598.           float rotation, char xAlign, char yAlign)
  599. {
  600.      float yStep = 0.0;
  601.      
  602.      switch (yAlign)
  603.      {
  604.      case 'C':
  605.      case 'c':
  606.       yStep = 0.4;
  607.       break;
  608.      
  609.      case 'T':
  610.      case 't':
  611.       yStep = 0.8;
  612.       break;
  613.      }
  614.      
  615.      switch (xAlign)
  616.      {
  617.      case 'C':
  618.      case 'c':
  619.       drawTextPS( string, x, y, fontSize, rotation, 0.5, yStep,
  620.              "Helvetica" );
  621.       break;
  622.       
  623.      case 'R':
  624.      case 'r':
  625.       drawTextPS( string, x, y, fontSize, rotation, 1.0, yStep,
  626.              "Helvetica" );
  627.       break;
  628.       
  629.      case 'L':
  630.      case 'l':
  631.      default:
  632.       drawTextPS( string, x, y, fontSize, rotation, 0.0, yStep,
  633.              "Helvetica" );
  634.       break;
  635.      }
  636.      
  637.      return 0;
  638. }
  639.  
  640.  
  641.  
  642. int drawColor2D_NeXT(int nXBins, int nYBins, rectangle *marginRect,
  643.              float *data, float binMin, float binMax, int useColor )
  644. {
  645.      int  iBin, iYBin;
  646.      int totBins = nXBins * nYBins;
  647.      float xlo = marginRect->origin.x;
  648.      float xhi = xlo + marginRect->size.width;
  649.      float ylo = marginRect->origin.y;
  650.      float yhi = ylo + marginRect->size.height;
  651.      float deltaX = (xhi - xlo) / nXBins;
  652.      float deltaY = (yhi - ylo) / nYBins;
  653.      NXRect *rects;
  654.      int iRect, nRects;
  655.      int rectChunk = 30;    /* >40 rects at a time seems to overflow PS */
  656.      float *grays;
  657.      float colorScale, blueHue, magHue, saturation, brightness;
  658.      float grayScale, nearWhite = 0.9;
  659.      float  xCoord, yCoord;
  660.      int i;
  661.      NXColor myColor;
  662.      float myHue;
  663.      
  664.      /*
  665.       * alloc space for every rect, 
  666.       * even though we will only draw the non-zero ones
  667.       */
  668.      if ((rects = (NXRect *) malloc (totBins * sizeof (NXRect))) == NULL)
  669.      {
  670.       h_error("drawColor2D_NeXT - memory exceeded ");
  671.       return -1;
  672.      }
  673.      
  674.      if ((grays = (float *) malloc (totBins * sizeof (float))) == NULL)
  675.      {
  676.       h_error("drawColor2D_NeXT - memory exceeded ");
  677.       return -1;
  678.      }
  679.      
  680.      /* 
  681.       * this routine leaves color in unpredictable state, 
  682.       * so we need a gsave/grestore
  683.       */ 
  684.      PSgsave();    
  685.      
  686.      if (binMin == binMax)
  687.       grayScale = 1.0;
  688.      else 
  689.       grayScale = nearWhite / (binMax - binMin);
  690.      xCoord = xlo;
  691.      yCoord = ylo;
  692.      iYBin = 0;
  693.      iRect = 0;
  694.      for (iBin = 0; iBin < totBins; iBin++)
  695.      {
  696.       /* bins are arranged as bins[x][y] with y changing fastest */
  697.       if (data[iBin] != 0)
  698.       {
  699.            NXSetRect (&rects[iRect], xCoord, yCoord, deltaX, deltaY);
  700.            /* 
  701.         * we set the grey value to the range: 
  702.         *  black (most) to nearWhite (least)
  703.         */
  704.            grays[iRect] = (binMax - data[iBin]) * grayScale;
  705.            iRect ++;
  706.       }
  707.       yCoord += deltaY;
  708.       iYBin++;
  709.       if ( iYBin == nYBins) 
  710.       {
  711.            iYBin = 0;
  712.            yCoord = ylo;
  713.            xCoord += deltaX;
  714.       }
  715.      }
  716.      
  717.      if (! useColor)
  718.      {
  719.       /* do the greyscale version */
  720.       for (i = 0; i < iRect; i += rectChunk)
  721.       {
  722.            nRects = rectChunk;
  723.            if  ((iRect - i) < rectChunk)  nRects = (iRect - i);
  724.            NXRectFillListWithGrays (&rects[i], &grays[i], nRects);
  725.       }
  726.      }
  727.      else
  728.      {
  729.       /* do the color version */
  730.       
  731.       /* set background to black */
  732.       NXSetColor (NX_COLORBLACK);
  733.       NXRectFill ((NXRect *) marginRect);
  734.       
  735.       /* establish the color scale */
  736.       NXConvertColorToHSB (NX_COLORBLUE, &blueHue, 
  737.                    &saturation, &brightness);
  738.       NXConvertColorToHSB (NX_COLORMAGENTA, &magHue, 
  739.                    &saturation, &brightness);
  740.       
  741.       /* 
  742.        * start at magenta (hot), increase to 1.0, 
  743.        * then wraparound to 0.0 and up to blue (cold)
  744.        */
  745.       colorScale = (1.0 - magHue + blueHue) / nearWhite;
  746.       
  747.       for (i=0; i < iRect; i++)
  748.       {
  749.            myHue = magHue + (grays[i]  * colorScale);
  750.            if (myHue > 1.0) myHue = myHue - 1.0;
  751.            myColor = NXConvertHSBToColor (myHue, 1.0, 1.0);
  752.            NXSetColor (myColor);
  753.            NXRectFill (&rects[i]);
  754.       }
  755.      }
  756.      free (rects);
  757.      free (grays);
  758.      
  759.      /*
  760.       * color/gray is left unpredictable, so we need a gsave/grestore 
  761.       */
  762.      PSgrestore();
  763.      return 0;
  764. }
  765.  
  766.  
  767. int drawLego2D_NeXT(rectangle *marginRect)
  768. {
  769.      /* set fontsize to 0.5 * top margin, with a max of 24.0 points */
  770.      float fontHeight= 0.2 * marginRect->origin.y;    
  771.      if (fontHeight > 24.0) fontHeight = 24.0;
  772.      
  773.      drawText_NeXT("Not implemented yet.", 
  774.         marginRect->origin.x + marginRect->size.width*0.5,
  775.         marginRect->origin.y + marginRect->size.height*0.5,
  776.         fontHeight,0.0,'c','c');
  777.      return 0;
  778. }
  779.  
  780. int shade_NeXT(float xlow, float xhigh, float ylow, float yhigh )
  781. {
  782.      NXRect myRect;
  783.      
  784.      PSgsave();
  785. /*     PSsetalpha(0.0);*/
  786.      PSsetgray(0.6);    
  787.      NXSetRect(&myRect, xlow, ylow, (xhigh-xlow),(yhigh-ylow));
  788.      NXRectFill(&myRect);
  789.      PSgrestore();
  790.      
  791.      return 0;
  792. }
  793.  
  794.